﻿using FlyingEye.Consts;
using FlyingEye.DeviceMaintenance;
using FlyingEye.DeviceMaintenance.Repositories;
using FlyingEye.Exceptions;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Validation;

namespace FlyingEye.DeviceMaintenanceServices
{
    /// <summary>
    /// 设备部件服务
    /// </summary>
    public class DevicePartService : ApplicationService
    {
        private readonly IDevicePartRepository _devicePartRepository;

        private readonly IDeviceMaintenanceRepository _deviceMaintenanceRepository;

        private readonly IDevicePartCheckItemRepository _devicePartCheckItemRepository;

        private readonly MaintenanceRecordService _maintenanceRecordService;

        public DevicePartService(
            IDevicePartRepository devicePartRepository,
            IDeviceMaintenanceRepository deviceMaintenanceRepository,
            IDevicePartCheckItemRepository devicePartCheckItemRepository,
            MaintenanceRecordService maintenanceRecordService)
        {
            _devicePartRepository = devicePartRepository;
            _deviceMaintenanceRepository = deviceMaintenanceRepository;
            _devicePartCheckItemRepository = devicePartCheckItemRepository;
            _maintenanceRecordService = maintenanceRecordService;
        }

        public async Task<DevicePartResponse> GetAsync(Guid id)
        {
            var model = await _devicePartRepository.FindAsync(id);

            if (model == null)
            {
                throw new ResourceNotFoundException(nameof(id));
            }

            return ObjectMapper.Map<DevicePartModel, DevicePartResponse>(model);
        }

        public async Task UpdateMaintenanceStepAsync(Guid id, StepActionRequest stepAction)
        {
            if (stepAction.Action == StepAction.Revert)
            {
                await this.RevertMaintenanceStepAsync(id);
            }
            else
            if (stepAction.Action == StepAction.Advance)
            {
                await this.AdvanceMaintenanceStepAsync(id);
            }
        }

        public async Task<DevicePartResponse?> FindByNameAsync(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new AbpValidationException("名字不能为空！");

            var model = await _devicePartRepository.FindAsync(item => item.DevicePartName == name);

            if (model != null)
            {
                return ObjectMapper.Map<DevicePartModel, DevicePartResponse>(model);
            }

            return null;
        }

        /// <summary>
        /// 获取项目下得所有部件
        /// </summary>
        public async Task<List<DevicePartResponse>> GetByDeviceMaintenanceAsync(Guid deviceMaintenanceId)
        {
            var list = await _devicePartRepository.GetListAsync(item => item.DeviceMaintenanceId == deviceMaintenanceId);

            return ObjectMapper.Map<List<DevicePartModel>, List<DevicePartResponse>>(list);
        }

        /// <summary>
        /// 插入一个部件
        /// </summary>
        public async Task<DevicePartResponse> InsertAsync(CreateDevicePartRequest devicePart)
        {
            if (!await _deviceMaintenanceRepository.AnyAsync(item => item.Id == devicePart.DeviceMaintenanceId))
            {
                throw new ResourceNotFoundException($"项目[{devicePart.DeviceMaintenanceId}]不存在。");
            }

            if (await _devicePartRepository.AnyAsync(
                 item => item.DevicePartName == devicePart.DevicePartName
                 && item.DeviceMaintenanceId == devicePart.DeviceMaintenanceId))
            {
                throw new AbpValidationException($"在[{devicePart.DeviceMaintenanceId}]项目中，部件名称[${devicePart.DevicePartName}]已经被使用。");
            }

            var model = ObjectMapper.Map<CreateDevicePartRequest, DevicePartModel>(devicePart);

            model = await _devicePartRepository.InsertAsync(model);

            return ObjectMapper.Map<DevicePartModel, DevicePartResponse>(model);
        }

        /// <summary>
        /// 更新一个部件
        /// </summary>
        public async Task<DevicePartResponse> UpdateAsync(UpdateDevicePartRequest devicePart)
        {
            if (!await _deviceMaintenanceRepository.AnyAsync(item => item.Id == devicePart.DeviceMaintenanceId))
            {
                throw new ResourceNotFoundException($"项目[{devicePart.DeviceMaintenanceId}]不存在。");
            }

            if (await _devicePartRepository.AnyAsync(
                item => item.DevicePartName == devicePart.DevicePartName
                && item.DeviceMaintenanceId == devicePart.DeviceMaintenanceId))
            {
                throw new BusinessOperationException($"部件名称[${devicePart.DevicePartName}]已经被使用。");
            }

            var model = await _devicePartRepository.FindAsync(devicePart.Id);

            if (model == null)
            {
                throw new ResourceNotFoundException($"部件[{devicePart.Id}]不存在。");
            }

            ObjectMapper.Map<UpdateDevicePartRequest, DevicePartModel>(devicePart, model);

            model = await _devicePartRepository.UpdateAsync(model);

            return ObjectMapper.Map<DevicePartModel, DevicePartResponse>(model);
        }

        /// <summary>
        /// 删除一个部件
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteAsync(Guid id)
        {
            if (!await _devicePartRepository.AnyAsync(item => item.Id == id))
            {
                throw new ResourceNotFoundException($"部件[{id}]不存在。");
            }

            await _devicePartRepository.DeleteAsync(id);
        }

        /// <summary>
        /// 开始维护设备
        /// </summary>
        public async Task StartMaintainingAsync(Guid id)
        {
            var partModel = await _devicePartRepository.FindAsync(id);

            if (partModel == null)
            {
                throw new ResourceNotFoundException($"部件[{id}]不存在。");
            }

            if (partModel.MaintenanceStatus == MaintenanceStatus.UNDER_MAINTENANCE)
            {
                throw new BusinessOperationException($"部件[{id}]正在维护中。");
            }

            // 将部件状态设置成维护中
            partModel.MaintenanceStatus = MaintenanceStatus.UNDER_MAINTENANCE;

            // 创建一个维护记录
            await _maintenanceRecordService.InsertAsync(
                new CreateMaintenanceRecordRequest(
                    devicePartId: partModel.Id,
                    maintenanceStep: MaintenanceStep.START,
                    true,
                    null));
        }

        /// <summary>
        /// 结束保养
        /// </summary>
        public async Task EndMaintainingAsync(Guid id)
        {
            var partModel = await _devicePartRepository.FindAsync(id);

            if (partModel == null)
            {
                throw new ResourceNotFoundException($"部件[{id}]不存在。");
            }

            if (partModel.MaintenanceStatus != MaintenanceStatus.UNDER_MAINTENANCE)
            {
                throw new BusinessOperationException($"部件[{id}]并没有维护。");
            }

            var step = await GetCurrentStepAsync(id);

            if (step != MaintenanceStep.COMPLETED)
            {
                throw new BusinessOperationException("部件维护未完成。");
            }

            var record = await _maintenanceRecordService.FindActiveRecordAsync(id);

            if (record == null)
            {
                throw new BusinessOperationException($"部件[{id}]没有正在维护中的记录。");
            }

            await _maintenanceRecordService.CloseAsync(record.Id);

            // 终止维护后，重置部件状态
            partModel.MaintenanceStatus = MaintenanceStatus.RUNING;

            await _devicePartRepository.UpdateAsync(partModel);
        }

        /// <summary>
        /// 取消维护
        /// </summary>
        public async Task CancelMaintainingAsync(Guid id, string reason)
        {
            var partModel = await _devicePartRepository.FindAsync(id);

            if (partModel == null)
            {
                throw new ResourceNotFoundException($"部件[{id}]不存在。");
            }

            if (partModel.MaintenanceStatus != MaintenanceStatus.UNDER_MAINTENANCE)
            {
                throw new BusinessOperationException($"部件[{id}]没有维护。");
            }

            var record = await _maintenanceRecordService.FindActiveRecordAsync(partModel.Id);

            if (record == null)
            {
                throw new BusinessOperationException($"部件[{id}]没有正在维护中的记录。");
            }

            await _maintenanceRecordService.CancelAsync(record.Id, reason);

            // 终止维护后，重置部件状态
            partModel.MaintenanceStatus = MaintenanceStatus.RUNING;

            await _devicePartRepository.UpdateAsync(partModel);
        }

        /// <summary>
        /// 推进到下一个维护步骤
        /// </summary>
        public async Task AdvanceMaintenanceStepAsync(Guid id)
        {
            var partModel = await _devicePartRepository.FindAsync(id);

            if (partModel == null)
            {
                throw new ResourceNotFoundException($"部件[{id}]不存在。");
            }

            if (partModel.MaintenanceStatus != MaintenanceStatus.UNDER_MAINTENANCE)
            {
                throw new BusinessOperationException($"部件[{id}]没有维护。");
            }

            var record = await _maintenanceRecordService.FindActiveRecordAsync(partModel.Id);

            if (record == null)
            {
                throw new BusinessOperationException($"部件[{id}]没有正在维护中的记录。");
            }

            await _maintenanceRecordService.AdvanceToNextStepAsync(record.Id);
        }

        /// <summary>
        /// 返回到上一个维护步骤
        /// </summary>
        public async Task RevertMaintenanceStepAsync(Guid id)
        {
            var partModel = await _devicePartRepository.FindAsync(id);

            if (partModel == null)
            {
                throw new ResourceNotFoundException($"部件[{id}]不存在。");
            }

            if (partModel.MaintenanceStatus != MaintenanceStatus.UNDER_MAINTENANCE)
            {
                throw new BusinessOperationException($"部件[{id}]没有维护。");
            }

            var record = await _maintenanceRecordService.FindActiveRecordAsync(partModel.Id);

            if (record == null)
            {
                throw new BusinessOperationException($"部件[{id}]没有正在使用的维护记录。");
            }

            await _maintenanceRecordService.RevertToPreviousStepAsync(record.Id);
        }

        public async Task<string> GetCurrentStepAsync(Guid id)
        {
            var record = await GetCurrentRecordAsync(id);

            return record.MaintenanceStep;
        }

        public async Task<MaintenanceRecordResponse> GetCurrentRecordAsync(Guid id)
        {
            var partModel = await _devicePartRepository.FindAsync(id);

            if (partModel == null)
            {
                throw new ResourceNotFoundException($"部件[{id}]不存在。");
            }

            if (partModel.MaintenanceStatus != MaintenanceStatus.UNDER_MAINTENANCE)
            {
                throw new BusinessOperationException($"部件[{id}]没有维护。");
            }

            var record = await _maintenanceRecordService.FindActiveRecordAsync(id);

            if (record == null)
            {
                throw new BusinessOperationException($"部件[{id}]没有正在使用的维护记录。");
            }

            return record;
        }
    }
}
